
#include <BFile>
#include <BSonDocument>
#include "member_BSonDocument.h"
#include "member_BSonNode.h"

using namespace BWE;

#define member					(*(member_BSonDocument*)_ptr)
#define member_allocate()		_ptr = new member_BSonDocument(this)
#define member_release()		delete (member_BSonDocument*)_ptr

BSonDocument::BSonDocument()
{
	member_allocate();
}
BSonDocument::~BSonDocument()
{
	member_release();
}

bool BSonDocument::setFormat(const BString& format)
{
	if (member.format.text != format)
	{
		member.format.fromString(format);
		return true;
	}
	return true;
}
const BString& BSonDocument::format() const
{
	return member.format.text;
}

BSonNode* BSonDocument::load(const BString& fileName)
{
	BFile file(fileName);
	if (file.open(IO_ReadText))
	{
		return read(file);
	}
	return 0;
}
bool BSonDocument::save(const BString& fileName, const BSonNode* root) const
{
	if (!root)
		return false;
	BFile file(fileName);
	if (file.open(IO_WriteText))
	{
		return write(file, root);
	}
	return false;
}
bool BSonDocument::save(const BString& fileName) const
{
	if (!member.node)
		return false;
	BFile file(fileName);
	if (file.open(IO_Write))
	{
		return write(file, member.node);
	}
	return false;
}

BSonNode* BSonDocument::read(const BString& sontext)
{
	member.node = 0;
	member.last = 0;
	BString name;
	char code = 0;
	int pos = 0;
	while (pos < sontext.size())
	{
		code = sontext[pos++];
		if (code == '\n')
			member.last = code;
		if (code == '{')
		{
			name.trimmed();
			member.node = new BSonNode(name);
			member.readNode(member.node, sontext, pos, 0);
			son_member(member.node)->format.head_prev = member.last;
			break;
		}
		if (code == '}')
			return 0;
		name.append(code);
	}
	member.makeFormat(member.node);
	return member.node;
}
bool BSonDocument::write(BString& sontext, const BSonNode* root) const
{
	if (!root)
		return false;
	member.writeNode(root, sontext, 0);
	return true;
}
bool BSonDocument::write(BString& sontext) const
{
	if (!member.node)
		return false;
	member.writeNode(member.node, sontext, 0);
	return true;
}

BSonNode* BSonDocument::read(const BStream& stream)
{
	member.node = 0;
	member.last = 0;
	BString name;
	char code = 0;
	while (stream.read(code))
	{
		if (code == '\n')
			member.last = code;
		if (code == '{')
		{
			name.trimmed();
			member.node = new BSonNode(name);
			member.readNode(member.node, stream, 0);
			son_member(member.node)->format.head_prev = member.last;
			break;
		}
		if (code == '}')
			return 0;
		name.append(code);
	}
	member.makeFormat(member.node);
	return member.node;
}
bool BSonDocument::write(BStream& stream, const BSonNode* root) const
{
	if (!root)
		return false;
	member.writeNode(root, stream, 0);
	return true;
}

void BSonDocument::setNode(BSonNode* node)
{
	member.node = node;
}
BSonNode* BSonDocument::node()
{
	return member.node;
}
